package com.zz.common.datasource;

import com.zz.common.entity.ClientConfig;
import com.zz.common.entity.User;
import com.zz.common.entity.UserClient;
import com.zz.common.exception.TunnelException;
import com.zz.common.utils.ObjectUtil;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 数据源顶层抽象，提供默认数据缓存策略
 */
public abstract class AbstractDataSource implements DataSource {

    private final static Map<String, User> userInfoCache = new ConcurrentHashMap<>();
    private final static Map<String, List<UserClient>> userClientCache = new ConcurrentHashMap<>();
    private final static Map<String, List<ClientConfig>> clientConfigCache = new ConcurrentHashMap<>();

    @Override
    public User authorize(String username, String password) {
        if (ObjectUtil.isEmptys(username, password)) {
            throw new TunnelException("授权失败，账号：%s, 密码：%s", username, password);
        }
        User authUser = userInfoCache.get(username);
        if (Objects.isNull(authUser)) {
            authUser = authorizeBySource(username, password);
            Optional.ofNullable(authUser).orElseThrow(() -> new TunnelException("授权失败，账号：%s, 密码：%s", username, password));
            userInfoCache.put(username, authUser);
        }
        if (!password.equals(authUser.getPassword())) {
            throw new TunnelException("授权失败，账号：%s, 密码：%s", username, password);
        }
        return authUser;
    }

    @Override
    public List<UserClient> getUserClient(String userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        List<UserClient> userClients = userClientCache.get(userId);
        if (ObjectUtil.isEmpty(userClients)) {
            userClients = getUserClientBySource(userId);
            if (ObjectUtil.isEmpty(userClients)) {
                return Collections.emptyList();
            }
            userClientCache.put(userId, userClients);
        }
        return userClients;
    }

    @Override
    public List<ClientConfig> getClientConfig(String clientId) {
        if (ObjectUtil.isEmpty(clientId)) {
            return Collections.emptyList();
        }
        List<ClientConfig> clientConfigs = clientConfigCache.get(clientId);
        if (ObjectUtil.isEmpty(clientConfigs)) {
            clientConfigs = getClientConfigBySource(clientId);
            if (ObjectUtil.isEmpty(clientConfigs)) {
                return Collections.emptyList();
            }
            clientConfigCache.put(clientId, clientConfigs);
        }
        return clientConfigs;
    }

    @Override
    public void init() {
        initSource();
    }

    @Override
    public void clear() {
        userInfoCache.clear();
        userClientCache.clear();
        clientConfigCache.clear();
    }

    /**
     * 初始化数据源
     */
    public abstract void initSource();

    /**
     * 清空缓存数据
     */
    public abstract void clearSource();
    /**
     * 从数据源认证
     * @param username
     * @param password
     * @return
     */
    public abstract User authorizeBySource(String username, String password);

    /**
     * 从数据源获取客户端信息
     * @param userId
     * @return
     */
    public abstract List<UserClient> getUserClientBySource(String userId);

    /**
     * 从数据源获取配信息
     * @param clientId
     * @return
     */
    public abstract List<ClientConfig> getClientConfigBySource(String clientId);


}
